class MapLayer extends egret.DisplayObjectContainer {
    private _sim: any;
    private _goals: any[];

    private _views: {[key:string]: View} = {};
    public constructor() {
        super();

        var bg = new egret.Bitmap();
        this.addChild(bg);
        RES.getResAsync('fightBg_jpg', () => {
            let tex = RES.getRes('fightBg_jpg');
            bg.texture = tex;
        }, this);

        this.init();
    }

    public init(): void {
        // parameter descriptions are given here: http://gamma.cs.unc.edu/RVO2/documentation/2.0/params.html
    /**
     *  timeStep 	The time step of the simulation. Must be positive.
        neighborDist 	The default maximal distance (center point to center point) to other agents a new agent takes into account in the navigation. The larger this number, the longer he running time of the simulation. If the number is too low, the simulation will not be safe. Must be non-negative.
        maxNeighbors 	The default maximal number of other agents a new agent takes into account in the navigation. The larger this number, the longer the running time of the simulation. If the number is too low, the simulation will not be safe.
        timeHorizon 	The default minimal amount of time for which a new agent's velocities that are computed by the simulation are safe with respect to other agents. The larger this number, the sooner an agent will respond to the presence of other agents, but the less freedom the agent has in                    choosing its velocities. Must be positive.
        timeHorizonObst 	The default minimal amount of time for which a new agent's velocities that are computed by the simulation are safe with respect to obstacles. The larger this number, the sooner an agent will respond to the presence of obstacles, but the less freedom the agent has in                          choosing its velocities. Must be positive.
        radius 	    The default radius of a new agent. Must be non-negative.
        maxSpeed 	The default maximal speed of a new agent. Must be non-negative.
        velocity 	The default initial two-dimensional linear velocity of a new agent (optional).
        */
        this._sim = new RVO.Simulator(2, 50, 5, 10, 10, 7, 1, [0, 0])
        this._goals = [];

        let idx = 0
        for (let i = 0; i < 20; i++) {
            for (let j = 0; j < 20; j++) {
                let px = 100 + i * 30;
                let py = 0 + j * 30;
                let point = [px, py];

                this._sim.addAgent(point);

                let view = new View();
                view.init('circle_png');
                view.setEnemyRange(400, 799);
                this.addChild(view);
                view.setId(idx);

                this._views[idx++] = view;
            }
        }
        
        for (let i = 0; i < 20; i++) {
            for (let j = 0; j < 20; j++) {
                let px = 100 + i * 30;
                let py = 650 + j * 30;
                let point = [px, py];

                this._sim.addAgent(point);

                let view = new View();
                view.init("rect_png");
                view.setEnemyRange(0, 399);
                this.addChild(view);
                view.setId(idx);

                this._views[idx++] = view;
            }
        }
    }

    public deathView(id: number): void {
        let view: View  = this._views[id];
        view.destroy();
        delete this._views[id];

        //清空敌人
        for (let key in this._views) {
            let view = this._views[key];
            let targetView = view.getTargetView();
            if (targetView && targetView.getId() == id) {
                view.setTarget(null);
            }
        }
    }

    public update(dt: number): void {
        for (let key in this._views) {
            let view: View = this._views[key];
            view.update(dt);

            let id = view.getId();
            let targetView = view.getTargetView();
            if (targetView) {
                let pos = targetView.getPos();
                this._goals[id] = [pos.x, pos.y];
            } else {
                let pos = view.getPos();
                this._goals[id] = [pos.x, pos.y];
            }
        }

        this.updateVisualization(this._sim);
        this.setPreferredVelocities(this._sim, this._goals);
        this._sim.doStep();
    }

    // draws the agents
    public updateVisualization(sim) {
        for (let i = 0, len = sim.agents.length; i < len; i ++) {
            let agent = sim.agents[i];
            if (i == 10) {
                agent.maxSpeed = 10;
            }
            
            let id = agent.id;
            let px = agent.position[0]
            let py = agent.position[1]
            let view = this._views[i];
            if (view) {
                view.setPos(px, py);
            } else {
                agent.radius = 0;
            }
        }
    }

    //assigns new velocities to all the agents
    public setPreferredVelocities(sim, goals) {
        for (let i = 0, len = sim.agents.length; i < len; i ++) {
            let goalVector = RVO.Vector.subtract(goals[i], sim.agents[i].position);

            if (sim.agents[i].position[0] <= 0) {
                sim.agents[i].position[0] = 0;
            } else if (sim.agents[i].position[0] >= 750) {
                sim.agents[i].position[0] = 750;
            }

            if (sim.agents[i].position[1] <= 0) {
                sim.agents[i].position[1] = 0;
            } else if (sim.agents[i].position[1] >= 1334) {
                sim.agents[i].position[1] = 1334;
            }

            if (RVO.Vector.absSq(goalVector) > 1) {
                goalVector = RVO.Vector.normalize(goalVector);
            }
            sim.agents[i].prefVelocity = goalVector;
        }
    }

    public getViews(): {[key:string]: View} {
        return this._views;
    }
}
